home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / src / dragclass.lha / drag_example / drag.class < prev    next >
Encoding:
Text File  |  1995-04-04  |  23.1 KB  |  815 lines

  1. ////
  2. ////  ATTN! This Class needs animtools from "RKM Libraries"
  3. ////        since that package is (c) by CBM, U must get
  4. ////        somewhere else ...
  5. ////
  6.  
  7. //
  8. // 17-04-94
  9. //  es laeuft nun anscheinend alles, beginne nun mit dem cleanup
  10. // oha -  etwas klappt noch nicht (bzw. nicht mehr...):
  11. //  2x Selection eines Gadgets laesst es in der Falschen Farbe rendern ...
  12. //
  13. // Brauche bringend ein Threshold ...
  14. //  - Chris mag es nicht ... naja sowas gehoert in Prefs ...
  15. //
  16.  
  17. PRIVATE_DEFINES // intern, steuerung der codegeneration
  18. //      TEST      1
  19. //      MYDEBUG 1
  20.  
  21.  
  22. CLASS        drag
  23. SUPERCLASS  "gadgetclass",NULL
  24.  
  25. ////////////////////////////////////////
  26.  
  27. FIRST_ATTR_NUM TAG_USER+1728
  28. FIRST_METH_NUM        1728
  29.  
  30. INCLUDES // extern sichtbar
  31.     <intuition/gadgetclass.h>
  32.     <intuition/cghooks.h>
  33.  
  34. PRIVATE_INCLUDES // intern
  35.     "animtools.h"
  36. //      "animtools_proto.h"
  37.     <string.h>
  38.     <graphics/gels.h>
  39.     <lists.h>
  40.     <clib/macros.h>
  41.  
  42. LIBRARIES
  43.     exec
  44.     intuition
  45.     utility
  46.     graphics
  47.     layers
  48.  
  49. ////////////////////////////////////////
  50.  
  51. DEFINES // extern sichtbar
  52.     DRAGNAME "draggclass"
  53.  
  54. PRIVATE_DEFINES // intern
  55.  
  56.     IEQUALIFIER_ANYSHIFT    (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  57.  
  58.     BORDER_WIDTH        4
  59.     BORDER_HEIGHT        4
  60.     THRESHOLD_X        4
  61.     THRESHOLD_Y        4
  62.  
  63.     // INSTANCE FLAGS
  64.     FIX_WIDTH        (1 << 0) // Gadget cannot modify its Width according to Image
  65.     FIX_HEIGHT        (1 << 1) // Gadget cannot modify its Height according to Image
  66. //    VISIBLE         (1 << 2) // Gadget BOB is Visible
  67.     SELECTED        (1 << 3) // Gadget is Selected (almost identical to GadgetFlag)
  68.     SUPPRESS_REDRAW     (1 << 4) // Gadget cannot be rendered now
  69.     FREE_PLACEMENT        (1 << 5) // Gadget can be placed everywhere in the current Window (IE Left & Top are not Fixed)
  70.     FREE_WINDOW        (1 << 6) // Gadget can be moved to another Window -- unused for now ...
  71.     NEWPOS            (1 << 7)
  72.  
  73.  
  74.     GADOB     ((struct Gadget *)o)
  75.     NBOB     inst->newbob
  76.     TBOB     inst->act_bob
  77.     GDATA     inst->gdata
  78.     GGI     inst->gdata->ginfo
  79.     GRP     (&inst->gdata->rp)
  80.     GVP     (&inst->gdata->screen->ViewPort)
  81.  
  82.     _DO  do{
  83.     _OD  }while(0)
  84.  
  85.     IS_SELECTED        (inst->flags & SELECTED)
  86.     MARK_SELECTED()         _DO inst->flags |=  SELECTED; GADOB->Flags |=  GFLG_SELECTED; _OD
  87.     MARK_UNSELECTED()       _DO inst->flags &= ~SELECTED; GADOB->Flags &= ~GFLG_SELECTED; _OD
  88.  
  89.     IS_VISIBLE        (inst->is_shown)
  90.     MAKE_INVISIBLE()        _DO inst->is_shown = 0; RemBob (TBOB);      _OD
  91.     MAKE_VISIBLE()          _DO inst->is_shown = 1; AddBob (TBOB, GRP); _OD
  92.  
  93.     INIT_GELS()             if (NULL == (GGI  = setupGelSys(GRP, 0x03))) { return GMR_NOREUSE; } else /* if */
  94.     MAKE_BOB()              if (NULL == (TBOB = makeBob(NBOB))) {          return GMR_NOREUSE; } else /* if */
  95.     KILL_BOB()              _DO if (TBOB)      freeBob      (TBOB, NBOB->nb_RasDepth); TBOB = NULL; _OD
  96.     EXIT_GELS(gd)           _DO if (gd->ginfo) cleanupGelSys(gd->ginfo, &gd->rp); gd->ginfo = NULL; _OD
  97.  
  98.     RECALC_WIDTH()          GADOB->Width = 2*BORDER_WIDTH + NBOB->nb_WordWidth*16;
  99.     RECALC_HEIGHT()         GADOB->Height= 2*BORDER_HEIGHT+ NBOB->nb_LineHeight;
  100.     RECALC_SIZES()          if (!(inst->flags & FIX_WIDTH)) RECALC_WIDTH(); if (!(inst->flags & FIX_HEIGHT)) RECALC_HEIGHT();
  101.  
  102.     SHOW_GELS(gd)           _DO SortGList (&((gd)->rp)); DrawGList (&((gd)->rp), &((gd)->screen->ViewPort)); WaitTOF (); _OD
  103.  
  104.     RENDER()                do_render  (o, (struct gpRender *)msg, inst)
  105.     DESELECT()              do_deselect(o, (Msg)msg, inst)
  106.     SELECT()                do_select  (o, (Msg)msg, inst)
  107.  
  108.         HIDE_ALL_BOBS()     do_hide_all    (GDATA)
  109.     REL_MOVE_ALL_BOBS(x,y)  do_move_all    (GDATA,x,y)
  110.         SHOW_ALL_BOBS()     do_show_all    (GDATA)
  111.     DESELECT_ALL_BOBS()     do_deselect_all(GDATA)
  112.  
  113.     TRY_TO_DROP()           _DO DQ(bug("*** DROPPING ***\n")); DisplayBeep(NULL); _OD
  114.     TRY_TO_DBLCLICK()       _DO DQ(bug("*** DBLCLICK ***\n")); DisplayBeep(NULL); _OD
  115.  
  116.     Forbid()
  117.     Permit()
  118.     LockLayers(li)
  119.     UnlockLayers(li)
  120.  
  121. ////////////////////////////////////////
  122.  
  123. CONTENTS // internal
  124.     struct MinNode     act_node;  // used to keep track of all selected drag-elements
  125.     Object        *act_self;  // needed to get the Objectinfo from the act_node
  126.     struct Bob    *act_bob;   // temp bob
  127.  
  128.     BYTE         is_shown;  // temp bob is visible
  129.     BYTE         is_selected;// similar to GADOB->Flags & SELECTED
  130.     UWORD         flags;     // padding flags
  131.  
  132.     struct newBob    *newbob;    // attribute render-data
  133.     struct GlobalData*gdata;    // a shortcut to cl->cl_Dispatcher.h_SubEntry
  134.     struct Window    *window;    // ... no alternative
  135.     struct timeval     lastclick; // to check a doubleclick
  136.  
  137. ////////////////////////////////////////////////////////////
  138. //
  139. //    Entry/Exit Code  for Instances
  140. //            (no En/Ex - Code for Class needed)
  141. //
  142. ////////////////////////////////////////////////////////////
  143.  
  144. OBJ_INIT    // to be: OM_NEW
  145.     inst->act_self    = o;
  146.     MARK_UNSELECTED();
  147.  
  148. OBJ_EXIT    // to be: OM_DISPOSE
  149.     DESELECT();
  150.  
  151.  
  152. ////////////////////////////////////////////////////////////
  153. //
  154. //  SUPPORT STRUCTURES
  155. //
  156. ////////////////////////////////////////////////////////////
  157.  
  158. STRUCTURES //external
  159.  
  160. ////////////////////////////////////////
  161. //
  162. //  Dies werden voraussichtlich "KompatibiliatesStrukturen"
  163. //  sie sind abhaengig von Bildschirm und von Art der
  164. //  Objecte;
  165. //  zB sei eine Subclass "IconClass" gegeben
  166. //  auf dem gleichen Bildschirm ausserdem noch eine Application
  167. //  die ebenfalls Dragobjecte verwendet, aber inkompatibel ist
  168. //  zu den Icons (zB ein GUIBuilder)
  169. //  wie verhindere ich nun, dass die Selektionen der Applikation
  170. //  mit denen der WB in einen Top geworfen werden ? - eben durch
  171. //  diese Struktur; alle Objecte, die solch eine STruktur teilen,
  172. //  koennen gemeinsam gebewgt werden, Shift-selectet werden, und
  173. //  sie deselectieren einander bei normaler Selection (ohne Shift)
  174. //  da es zB in einer Wb noch unterklassen von Icons geben kann,
  175. //  (was passiert wenn ich etwas auf ein anderes Volume schiebe,
  176. //  anstatt nur im akuellen Volume? wenn ich ein Volume auf ein
  177. //  anderes ziehe, dazu noch appicons ...)
  178. //  ist diese Teststruktur noch bei weitem nicht ausreichend;
  179. //  ich werde sie jedoch fuer diesen Protoypen nicht weiter ausbauen,
  180. //  schliesslich handelt es sich ja nur um eine "Studie"
  181. //
  182.  
  183. struct GlobalData {
  184.     int         num_selected;
  185.     struct MinList  list;  // all selected drag-objects
  186.     struct MinList  dests; // all registered drop-targets (a tree might be better)
  187.     struct GelInfo* ginfo; // once mor: all selected objects - here: their bobs
  188.     int         is_shown; // ginfo is (not) empty
  189.     ULONG        id; // future
  190.     struct Screen*  screen;
  191.     struct RastPort rp;     // copy of screen-rp
  192.  
  193.     // --- the following entries are to manage DoubleClicks
  194.     struct timeval  last_selection;
  195.     Object       *last_selected;
  196.  
  197.     // --- we keep track of all movements in order to be able to move all
  198.     //       dragged gadgets - if possible
  199.     WORD move_X, move_Y;
  200.  
  201.     // ---- we must also keep track, where the cursor was with the last
  202.     //        event, since ievent->iex/y are raw values ...
  203.     WORD last_X, last_Y;
  204. }; /* struct GlobalData */
  205.  
  206.  
  207.  
  208. ////////////////////////////////////////////////////////////
  209. //
  210. //  SUPPORT DATA AND FUNCTIONS
  211. //
  212. ////////////////////////////////////////////////////////////
  213.  
  214. SUPPORT // internal
  215.  
  216. ////////////////////////////////////////
  217. //
  218. //  ARRRRRRGHHHHHh ......
  219. //  Global Data ...
  220. //
  221. ////////////////////////////////////////
  222.  
  223. #ifdef Threshold
  224. static int dist_X, dist_Y;
  225. #endif
  226.  
  227. ////////////////////////////////////////
  228.  
  229. static void do_clear (Object *o, struct gpRender *msg, struct _CLASS *inst) {
  230. } /* do_clear */
  231.  
  232.  
  233.  
  234.  
  235. static void do_render(Object *o, struct gpRender *msg, struct _CLASS *inst) {
  236.     struct RastPort *rp;
  237.  
  238.  DQ(bug("  RENDER\n"));
  239.  
  240.     if (inst->flags & SUPPRESS_REDRAW)
  241.     return;
  242.  
  243.     if (msg->MethodID != GM_RENDER) {
  244.     if (!(msg->gpr_GInfo))
  245.         return;
  246.  
  247.     rp = ObtainGIRPort(msg->gpr_GInfo);
  248.     } else {
  249.     rp = msg->gpr_RPort;
  250.     } /* if */
  251.  
  252.     if (rp) {
  253.     UWORD back, shine, shadow;
  254.     UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
  255.  
  256.     if (!(IS_SELECTED)) { // If the gadget is selected, reverse the meanings of the pens
  257.         back   = pens[BACKGROUNDPEN];
  258.         shine  = pens[     SHINEPEN];
  259.         shadow = pens[    SHADOWPEN];
  260.     } else {
  261.         back   = pens[  FILLPEN];
  262.         shine  = pens[SHADOWPEN];
  263.         shadow = pens[ SHINEPEN];
  264.     } /* if */
  265.  
  266.     if (inst->flags & NEWPOS) { // --- Fully Erase the old gadget.
  267.         inst->flags &= ~ NEWPOS;
  268.         if (inst->flags & FREE_PLACEMENT) {
  269.         SetDrMd(rp, JAM1);
  270.         SetAPen(rp, pens[BACKGROUNDPEN]);
  271.         RectFill(rp, GADOB->LeftEdge,
  272.                  GADOB->TopEdge,
  273.                  GADOB->LeftEdge + GADOB->Width,
  274.                  GADOB->TopEdge  + GADOB->Height);
  275.         GADOB->TopEdge    += GDATA->move_Y;
  276.         GADOB->LeftEdge += GDATA->move_X;
  277.         } /* if */
  278.         // wir muessten nun noch einmal die ganze Liste
  279.         // durchgehen und alle gadgets neuzeichnen ...
  280.     } else {
  281.         SetDrMd(rp, JAM1);
  282.         SetAPen(rp, back);     // Erase the old gadget.
  283.         RectFill(rp, GADOB->LeftEdge,
  284.              GADOB->TopEdge,
  285.              GADOB->LeftEdge + GADOB->Width,
  286.              GADOB->TopEdge  + GADOB->Height);
  287.  
  288.         SetAPen(rp, shadow);   // Draw shadow edge.
  289.         Move(rp, GADOB->LeftEdge + 1, GADOB->TopEdge + GADOB->Height);
  290.         Draw(rp, GADOB->LeftEdge + GADOB->Width, GADOB->TopEdge + GADOB->Height);
  291.         Draw(rp, GADOB->LeftEdge + GADOB->Width, GADOB->TopEdge + 1);
  292.  
  293.         SetAPen(rp, shine);    // Draw shine edge.
  294.         Move(rp, GADOB->LeftEdge, GADOB->TopEdge + GADOB->Height - 1);
  295.         Draw(rp, GADOB->LeftEdge, GADOB->TopEdge);
  296.         Draw(rp, GADOB->LeftEdge + GADOB->Width - 1, GADOB->TopEdge);
  297.  
  298.         if (NBOB) {
  299.         struct Image im={ 0,0,                // left&top
  300.                   NBOB->nb_WordWidth*16,    // wid
  301.                   NBOB->nb_LineHeight,        // hig
  302.                   NBOB->nb_RasDepth,        // dep
  303.                   NBOB->nb_Image,        // imda
  304.                   NBOB->nb_PlanePick,        // ppck
  305.                   NBOB->nb_PlaneOnOff,        // poo
  306.                   NULL };            // next
  307.  
  308.         DrawImage(rp, &im, GADOB->LeftEdge + BORDER_WIDTH, GADOB->TopEdge + BORDER_HEIGHT);
  309.         } /* if  nbob */
  310.     } /* if dodraw */
  311.     } /* if rp */
  312.  
  313.     if (msg->MethodID != GM_RENDER) {
  314.     ReleaseGIRPort(rp);
  315.     } /* if */
  316.  
  317. } /* do_render */
  318.  
  319. ////////////////////////////////////////
  320.  
  321. static int do_select (Object *o, Msg msg, struct _CLASS *inst) {
  322.  
  323.  DQ(bug("select_self ...\n"));
  324.  
  325.     if (!(IS_SELECTED)) {
  326.     MARK_SELECTED();
  327.  
  328.     MAKE_BOB();
  329.  
  330.     if (GDATA) {
  331.         Forbid();
  332.         GDATA->num_selected ++;
  333.         AddTail((struct List*)&GDATA->list, (struct Node *)&inst->act_node);
  334.         Permit();
  335.     } /* if */
  336.     } /* if */
  337.  
  338.     return GMR_MEACTIVE;
  339. } /* do_select */
  340.  
  341. ////////////////////////////////////////
  342.  
  343. static void do_deselect (Object *o, Msg msg, struct _CLASS *inst) {
  344.  
  345.  DQ(bug("DEselect_self ...\n"));
  346.  
  347.     if (IS_SELECTED) {
  348.     MARK_UNSELECTED();
  349.  
  350.     if (IS_VISIBLE) {
  351.         MAKE_INVISIBLE();
  352.         if (GDATA)
  353.         SHOW_GELS(GDATA);
  354.     } /* if */
  355.  
  356.     if (GDATA) {
  357.  
  358.         Forbid();
  359.         Remove ((struct Node *)&inst->act_node);
  360.         GDATA->num_selected --;
  361.         Permit();
  362.  
  363.         if (GDATA->num_selected == 0) {
  364.         // ---- Nota Bene INIT/EXIT-GELS should better be put into CLASS_INIT/EXIT
  365.         //    but we do not have any Information 'bout Screens there;
  366.         //    worse - using MUI [;)] we do not have a permanent Screen.
  367.         EXIT_GELS(GDATA);
  368.         } /* if */
  369.     } /* if */
  370.  
  371.     KILL_BOB();
  372.     } /* if */
  373. } /* do_deselect */
  374.  
  375. ////////////////////////////////////////
  376.  
  377. //////////////////////////////////////////////////
  378. //
  379. //  WARNING!
  380. //
  381. //  the following routines are quite time-expensive,
  382. //  though they are called from within InputDevice;
  383. //  Sorry, but I do not know any workaround for that
  384. //  (ok, we could use GadTools way, but that's no
  385. //  Solution for a BOOPSI Object)
  386. //
  387. //////////////////////////////////////////////////
  388.  
  389. #define o inst->act_self
  390.  
  391. static void do_hide_all (struct GlobalData *gd) {
  392.     struct _CLASS *inst;
  393.  
  394.  DQ(bug("hide_all\n"));
  395.  
  396.     if (gd && gd->ginfo) {
  397.     Forbid();
  398.     for (inst = GetHead(&gd->list); inst; inst = GetSucc(inst)) {
  399.         MAKE_INVISIBLE();
  400.     } /* for */
  401.     Permit();
  402.  
  403.     SHOW_GELS(gd);
  404.     EXIT_GELS(gd);
  405.     } /* if */
  406. } /* do_hide_all */
  407.  
  408. ////////////////////////////////////////
  409.  
  410. static int do_show_all (struct GlobalData *gd) {
  411.     struct _CLASS *inst;
  412.  
  413.  DQ(bug("show_all\n"));
  414.  
  415.     if (!gd)
  416.     return GMR_NOREUSE;
  417.  
  418.     if (gd->num_selected > 0) {
  419.     if (!(gd->ginfo)) {
  420.         if (NULL == (gd->ginfo  = setupGelSys(&gd->rp, 0x03))) {
  421.         return GMR_NOREUSE;
  422.         } /* if */
  423.     } /* if */
  424.  
  425.     for (inst = GetHead(&gd->list); inst; inst = GetSucc(inst)) {
  426.         TBOB->BobVSprite->X  = inst->window->LeftEdge + GADOB->LeftEdge + BORDER_WIDTH;
  427.         TBOB->BobVSprite->Y  = inst->window->TopEdge  + GADOB->TopEdge  + BORDER_HEIGHT;
  428.         MAKE_VISIBLE();
  429.     } /* while */
  430.  
  431. // --- Immediately after ShowAll we are calling MoveAll, so there is no need
  432. //     to draw'em now; insted I'd rather only sort our gelslist here, and
  433. //     drop gelssorting in my other calls.
  434. //      SHOW_GELS(gd);
  435.     } /* if */
  436.     return GMR_MEACTIVE;
  437. } /* do_show_all */
  438.  
  439. ////////////////////////////////////////
  440.  
  441. static void do_move_all (struct GlobalData *gd, int x, int y) {
  442.     struct _CLASS *inst;
  443.  DQ(bug("move_all\n"));
  444.     if (gd && gd->ginfo) {
  445.     for (inst = GetHead(&gd->list); inst; inst = GetSucc(inst)) {
  446.         TBOB->BobVSprite->X +=x;
  447.         TBOB->BobVSprite->Y +=y;
  448.     } /* for */
  449.  
  450.     SHOW_GELS(gd);
  451.     } /* if */
  452. } /* do_move_all */
  453.  
  454. ////////////////////////////////////////
  455.  
  456. static void do_deselect_all (struct GlobalData *gd) {
  457.     struct _CLASS *inst;
  458.  
  459.  DQ(bug("deselect_all\n"));
  460.     if (gd && (gd->num_selected > 0)) {
  461.     do_hide_all(gd);
  462.  
  463.     for (inst = GetHead(&gd->list); inst;) {
  464.         APTR next;
  465.         struct TagItem tags[2] = { GA_Selected, 0, TAG_DONE };
  466.         next = GetSucc(inst);
  467. //          freeBob       (TBOB, NBOB->nb_RasDepth);
  468. //          TBOB = NULL;
  469. // SetGadgetAttrs  ((struct Gadget *)inst->act_self, inst->window, NULL, GA_Selected, FALSE, TAG_DONE);
  470.         SetGadgetAttrsA ((struct Gadget *)inst->act_self, inst->window, NULL, tags);
  471.         RefreshGList    ((struct Gadget *)inst->act_self, inst->window, NULL, 1);
  472.         inst = next;
  473.     } /* for */
  474.     } /* if */
  475. } /* do_deselect_all */
  476.  
  477. #undef o
  478.  
  479.  
  480. ////////////////////////////////////////
  481.  
  482. ////////////////////////////////////////////////////////////
  483. //
  484. // NEW OR CHANGED ATTRIBUTES
  485. //
  486. ////////////////////////////////////////////////////////////
  487.  
  488. ATTRIBUTE GDA_NewBob
  489.     $I NBOB = (APTR)val; RECALC_SIZES();
  490.     $G val    = (ULONG)NBOB;
  491.     $S if (!IS_SELECTED) NBOB = (APTR)val; else { DESELECT(); NBOB = (APTR)val; SELECT(); } RECALC_SIZES(); retval = 1;
  492.  
  493. ATTRIBUTE GA_Selected
  494.     $S if ((val) && !(IS_SELECTED)) { SELECT(); retval = 1; } else if ((!val) && (IS_SELECTED)) { DESELECT(); retval = 1; }
  495.     $U if ((val) && (!IS_SELECTED)) { SELECT();             } else if ((!val) && (IS_SELECTED)) { DESELECT(); }
  496.  
  497. ATTRIBUTE GDA_GData
  498.     $I GDATA = (APTR)val;
  499.     $G val     = (ULONG)GDATA;
  500.  
  501. ATTRIBUTE GDA_FreePlacement // object is moveable on the Window
  502.     $I if (val) inst->flags |= FREE_PLACEMENT; else inst->flags &= ~FREE_PLACEMENT;
  503.     $G val = (inst->flags & FREE_PLACEMENT) ? 1 : 0;
  504.  
  505. ATTRIBUTE GDA_NewPlacement // move, if You are free placeable
  506.     $S inst->flags |= NEWPOS; retval = 1;
  507.  
  508. ATTRIBUTE GA_Width
  509.     $I if (val) inst->flags |= FIX_WIDTH;  else { inst->flags &= ~FIX_WIDTH;  RECALC_WIDTH();  }
  510.     $S if (val) inst->flags |= FIX_WIDTH;  else { inst->flags &= ~FIX_WIDTH;  RECALC_WIDTH();  } retval = 1;
  511.  
  512. ATTRIBUTE GA_Height
  513.     $I if (val) inst->flags |= FIX_HEIGHT; else { inst->flags &= ~FIX_HEIGHT; RECALC_HEIGHT(); }
  514.     $S if (val) inst->flags |= FIX_HEIGHT; else { inst->flags &= ~FIX_HEIGHT; RECALC_HEIGHT(); } retval = 1;
  515.  
  516.  
  517.  
  518. // GFLG_REL-RIGHT/BOTTOM in fact cannot be set;
  519. // we do just try to make sure here, they can't be set
  520. // in the basic gadget structure by resetting them as
  521. // soon as they are set ...
  522. ATTRIBUTE    GA_RelRight
  523.     $I GADOB->Flags &= ~GFLG_RELRIGHT;
  524.     $S GADOB->Flags &= ~GFLG_RELRIGHT;
  525. ATTRIBUTE    GA_RelBottom
  526.     $I GADOB->Flags &= ~GFLG_RELBOTTOM;
  527.     $S GADOB->Flags &= ~GFLG_RELBOTTOM;
  528.  
  529.  
  530. ////////////////////////////////////////////////////////////
  531. //
  532. // NEW OR CHANGED METHODS
  533. //
  534. ////////////////////////////////////////////////////////////
  535.  
  536. METHOD GM_HITTEST struct gpHitTest*
  537.  
  538.     return GMR_GADGETHIT;
  539.  
  540. ////////////////////////////////////////
  541.  
  542. METHOD GM_RENDER struct gpRender*
  543.  
  544.     RENDER();
  545.     return 1;
  546.  
  547. ////////////////////////////////////////
  548.  
  549. METHOD GM_GOINACTIVE struct gpGoInactive*
  550.  
  551.     if (GDATA) {
  552.         HIDE_ALL_BOBS();
  553.         UnlockLayers(&GDATA->screen->LayerInfo);
  554.     } /* if */
  555.  
  556.     return 1;
  557.  
  558. ////////////////////////////////////////
  559.  
  560. METHOD GM_GOACTIVE struct gpInput*
  561.     ULONG retval;
  562.     struct InputEvent *ie;
  563.  
  564.     if (ie = msg->gpi_IEvent) { // only act on direct user-input
  565.         int inter;
  566.  
  567.         if (!GDATA) {
  568.         if (!IS_SELECTED) {
  569.             MARK_SELECTED();
  570.             RENDER();
  571.         } /* if */
  572.         return GMR_NOREUSE;
  573.         } /* if */
  574.  
  575.         // --- solange wir nix besseres wissen ...
  576.         inst->window  = msg->gpi_GInfo->gi_Window;
  577.         GDATA->screen = msg->gpi_GInfo->gi_Screen;
  578.         *GRP      = GDATA->screen->RastPort;
  579.         LockLayers(&GDATA->screen->LayerInfo);
  580.         GDATA->move_X = 0;
  581.         GDATA->move_Y = 0;
  582. #ifdef Threshold
  583.         dist_X = dist_Y = 0;
  584. #endif
  585.  
  586.         // --- I think, it is not necessary to free/reallocate/rerender our own data, if we are already selected
  587.         if ((inter = IS_SELECTED)) {
  588.         MARK_UNSELECTED();
  589.         inst->flags |= SUPPRESS_REDRAW;
  590.         } /* if */
  591.  
  592.         if (!(ie->ie_Qualifier & IEQUALIFIER_ANYSHIFT)) {
  593.         DESELECT_ALL_BOBS();
  594.         } /* if */
  595.  
  596.         if (inter) {
  597.         MARK_SELECTED();
  598.         inst->flags &= ~SUPPRESS_REDRAW;
  599.         } else {
  600.         SELECT();
  601.         RENDER();
  602.         } /* if */
  603.  
  604.         // --- Check for Doubleclick; putting it into HANDLEINPUT
  605.         //       would decrease speed, since the flag is checked on
  606.         //        every IEvent, so we have to put it here 8-(
  607.         if (inter && (o == GDATA->last_selected)) {
  608.         if (DoubleClick(GDATA->last_selection.tv_secs, GDATA->last_selection.tv_micro, ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro )) {
  609.             GDATA->last_selected = NULL;
  610.  
  611.             TRY_TO_DBLCLICK();
  612.  
  613.             return GMR_NOREUSE;
  614.         } /* if */
  615.         } /* if */
  616.         GDATA->last_selected  = o;
  617.         GDATA->last_selection = ie->ie_TimeStamp;
  618.  
  619.         GDATA->last_X = msg->gpi_Mouse.X;
  620.         GDATA->last_Y = msg->gpi_Mouse.Y;
  621.  
  622.         return GMR_MEACTIVE;
  623.     } else {
  624.         return GMR_NOREUSE;
  625.     } /* if */
  626.     return retval;
  627.  
  628. ////////////////////////////////////////
  629.  
  630. METHOD GM_HANDLEINPUT struct gpInput*
  631.     ULONG retval = GMR_MEACTIVE;
  632.     struct InputEvent *ie = msg->gpi_IEvent;
  633.     WORD deltaX, deltaY;
  634.  
  635. // extern char *class_name    (ULONG);
  636. // DQ(bug(" gpinfo: gi=%08lx ie=$%08lx te=$%08lx->%ld ms=(%3ld,%3ld)\n", msg->gpi_GInfo, ie, msg->gpi_Termination, *(msg->gpi_Termination), msg->gpi_Mouse.X, msg->gpi_Mouse.Y));
  637. // DQ(bug(" ie:  cl=$%02lx sc=$%02lx cd=$%04lx ql=$%04lx ea=$%08lx tv=(%d.%010ld)\n", ie->ie_Class, ie->ie_SubClass, ie->ie_Code, ie->ie_Qualifier, ie->ie_EventAddress, ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro));
  638. // DQ(bug(" %s\n", class_name(ie->ie_Class)));
  639.  
  640.  
  641. //    // --- Check for Doubleclick; putting it here would decrease
  642. //    //     speed, since the flag is checked on every IEvent ...
  643. //    //     pity, but can't help
  644. //    if (IS_CHECK_DBLCLICK) {
  645. //        MAKE_UNCHECKDBLCLICK();
  646. //        if (o == GDATA->last_selected) {
  647. //        if (DoubleClick(GDATA->last_selection.tv_secs, GDATA->last_selection.tv_micro, msg->gpi_InputEvent->ie_TimeStamp.tv_secs, msg->gpi_InputEvent->ie_TimeStamp.tv_micro )) {
  648. //            TRY_TO_DBLCLICK();
  649. //            return GMR_NOREUSE;
  650. //        } /* if */
  651. //        } /* if */
  652. //        GDATA->last_selected  = o;
  653. //        GDATA->last_selection = ie->ie_TimeStamp;
  654. //    } /* if */
  655.  
  656.  
  657.     if (ie->ie_Class != IECLASS_RAWMOUSE) {
  658.         return GMR_MEACTIVE;
  659.     } /* if */
  660.  
  661.     switch (ie->ie_Code) {
  662.     case SELECTUP: // --- drop! ... where ?
  663.         if (IS_VISIBLE) {
  664.         TRY_TO_DROP();
  665.         } /* if */
  666.         return GMR_NOREUSE;
  667.  
  668.     case MENUDOWN:        // --- abort or deselect all or only this one
  669.         if (!(ie->ie_Qualifier & IEQUALIFIER_ANYSHIFT))
  670.         DESELECT_ALL_BOBS();
  671.         else
  672.         if (!IS_VISIBLE) {
  673.             DESELECT();
  674.             RENDER();
  675.         } /* if */
  676.         return GMR_NOREUSE;
  677.  
  678.     default:
  679.         // --- securitycheck: haben wir ein selectup verpasst? ...
  680.         //       solange die Maus gedrueckt ist, weitermachen ...
  681.         if (!(ie->ie_Qualifier & IEQUALIFIER_LEFTBUTTON)) {
  682.         return GMR_NOREUSE;
  683.         } /* if */
  684.  
  685.         deltaX = msg->gpi_Mouse.X - GDATA->last_X;
  686.         deltaY = msg->gpi_Mouse.Y - GDATA->last_Y;
  687.         GDATA->last_X = msg->gpi_Mouse.X;
  688.         GDATA->last_Y = msg->gpi_Mouse.Y;
  689.  
  690.         // --- lass ihn hidden solange es geht, dann zecihnen,
  691.         //       ansonsten Position nachhalten ...
  692.         // --- ich wuerde gerne eine Minimale Bewegung einbauen,
  693.         //       einen Schwellenwert, unter dem keine Bobs dargestellt
  694.         //       werden.
  695.         if ((ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)) {
  696. #ifdef Threshold
  697.         if (!IS_VISIBLE) {
  698.             // --- Primitiver Threshold ...
  699.             //       die Routine Versagt, wenn
  700.             //       die Eingabe irgendwo zwischen 0 und THRESHOLD_?
  701.             //       endet ... (zB Selection,1 Pixel Movement,Release)
  702.             //       der naechste Bob wird falsch dargestellt 8-(
  703.             //       um das zu umgehen muessten wir die Weite in
  704.             //       GM_GO[IN]ACTIVE resetten, das geht aber nur mit
  705.             //       globalen daten ... (na gut, auch nicht schlechter
  706.             //       als statics)
  707.             //       da hat mir die alte version ja fast noch besser gefallen
  708.             // static int dist_X, dist_Y;
  709.             // static int rel_X, rel_Y;
  710.             dist_X += ABS(deltaX);
  711.             dist_Y += ABS(deltaY);
  712.             GDATA->move_X += deltaX;
  713.             GDATA->move_Y += deltaY;
  714.             if ((dist_X > THRESHOLD_X) || (dist_Y > THRESHOLD_Y)) {
  715.             SHOW_ALL_BOBS();
  716.             REL_MOVE_ALL_BOBS(GDATA->move_X, GDATA->move_Y);
  717.             dist_X = dist_Y = 0;
  718.             } /* if */
  719.         } else {
  720.             if ((deltaX || deltaY)) {
  721.             REL_MOVE_ALL_BOBS(deltaX, deltaY);
  722.             GDATA->move_X += deltaX;
  723.             GDATA->move_Y += deltaY;
  724.             } /* if */
  725.         } /* if */
  726. #else
  727.         if ((deltaX || deltaY)) {
  728.             if (!IS_VISIBLE)
  729.             SHOW_ALL_BOBS();
  730.             REL_MOVE_ALL_BOBS(deltaX, deltaY);
  731.             GDATA->move_X += deltaX;
  732.             GDATA->move_Y += deltaY;
  733.         } /* if */
  734. #endif
  735.         } else {
  736.         // --- hierfuer muesste ich die mauspos zwischenspeichern,
  737.         //     und die rel-werte jetzt bestimmen .... BWRRRRRRR
  738.         //     (bei jedem relmove aufaddieren)
  739.  DQ(bug("WARNING: **ABSMOUSE SKIPPED** \n", *(char*)0L));
  740. // reicht in ENFORCERHIT als Warnung ????????? 8^)
  741.         } /* if */
  742.  
  743.         return GMR_MEACTIVE;
  744.     } /* switch */
  745.  
  746.     return retval;
  747.  
  748.  
  749.  
  750.  
  751. ////////////////////////////////////////////////////////////
  752. //
  753. //  Minimal Test-Environment
  754. //
  755. ////////////////////////////////////////////////////////////
  756.  
  757. TEST_SUPPORT
  758.  
  759. #   define GEL_SIZE  4            /* number of lines in the bob     */
  760.  
  761.     /* data is 2 planes by 2 words by GEL_SIZE lines             */
  762.     WORD __chip bob_data[2 * 2 * GEL_SIZE] = {
  763.     /* plane 1 */
  764.     0xc000, 0xffff, 0xc000, 0x0fff, 0xc000, 0x0fff, 0xc000, 0xffff,
  765.     /* plane 2 */
  766.     0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc
  767.     };
  768.     NEWBOB myNewBob = {
  769.     bob_data, 2,  GEL_SIZE,
  770.     2, 3, 0, SAVEBACK | OVERLAY,
  771.     0, 8, 160, 100,  0,0,
  772.     };
  773.  
  774. struct GlobalData *gimme_gdata (int cls) {
  775.     static struct GlobalData gdata;
  776.     if (cls) {
  777.     memset    (&gdata, sizeof (gdata), 0);
  778.     NewList ((struct List *)&gdata.list);
  779.     } /* if */
  780.     return &gdata;
  781. } /* gimme_gdata */
  782.  
  783.  
  784.  
  785. TEST_WINDOW
  786.     WA_IDCMP, IDCMP_CLOSEWINDOW,
  787.     WA_Title, "DragClass TestWindow",
  788.     WA_Width, 300,
  789.     WA_Height, 100,
  790.  
  791. TEST_OBJECT test_ob
  792.     GA_Top,    50,
  793.     GA_Left,    50,
  794.     GDA_NewBob, &myNewBob,
  795.     GDA_GData,    gimme_gdata(1),
  796.     GDA_FreePlacement, 1,
  797.  
  798. TEST_OBJECT test_ob2
  799.     GA_Previous,test_ob,
  800.     GA_Top,    50,
  801.     GA_Left,   120,
  802.     GDA_NewBob, &myNewBob,
  803.     GDA_GData,    gimme_gdata(0),
  804.     GDA_FreePlacement, 1,
  805.  
  806. TEST_OBJECT test_ob3
  807.     GA_Previous,test_ob2,
  808.     GA_Top,    50,
  809.     GA_Left,   190,
  810.     GDA_NewBob, &myNewBob,
  811.     GDA_GData,    gimme_gdata(0),
  812.  
  813.  
  814.  
  815.